package com.glsc.ngateway.opmanage.controller.report;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.base.domain.mysql.opmanage.report.FileUploadLog;
import com.glsc.ngateway.common.base.domain.mysql.opmanage.report.fileupload.FileUploadRelateImport;
import com.glsc.ngateway.common.base.domain.mysql.opmanage.report.regulatory.RegRptDefine;
import com.glsc.ngateway.common.base.dto.opmanage.report.DerivativeResponse;
import com.glsc.ngateway.common.base.dto.opmanage.report.ExcelUploadDto;
import com.glsc.ngateway.common.base.dto.opmanage.report.ImportFileDto;
import com.glsc.ngateway.opmanage.aspect.JwtHelper;
import com.glsc.ngateway.opmanage.service.UserService;
import com.glsc.ngateway.opmanage.service.report.FileUploadService;
import com.glsc.ngateway.opmanage.service.report.RegulatoryReportService;
import com.glsc.ngateway.opmanage.service.report.excel.ExcelUploadService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("api/excelUpload")
@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
@Api(value = "excel上传controller", tags = {"excel上传接口"})
public class ExcelUploadController {

    private static final Map<String, List<String>> FILENAME_DEPARTMENT_MAP = Map.of(
            "固定收益部", Arrays.asList("固收", "固定收益部", "固收部"),
            "资金运营部", Arrays.asList("资金部", "资金运营部"),
            "股权衍生品部", Arrays.asList("股衍", "股权衍生品"),
            "证券投资部", Arrays.asList("证投", "证券投资部")
    );
    private static final List<String> DEPARTMENT_CAT_LIST = Arrays.asList("E01", "E02", "E03", "E04");

    @Autowired
    private FileUploadService fileUploadService;

    @Autowired
    private UserService userService;

    @Autowired
    private ExcelUploadService excelUploadService;

    @Autowired
    private RegulatoryReportService regulatoryReportService;

    @Value("${opmanage.nas.path.zyfile}")
    String nasPath = "";


    @Transactional
    @ApiOperation(value = "文件上传")
    @PostMapping("/importFileUpload")
    public DerivativeResponse upload(@RequestParam(required = false, value = "file") MultipartFile file,
                                     @RequestParam(required = false, value = "catid") String catid,
                                     @RequestParam(required = false, value = "bizdate") String bizdate,
                                     @RequestParam(required = false, value = "dimension1") String dimension1,
                                     HttpServletRequest request) throws IllegalStateException, IOException, JSONException {
        try {
            if (file == null || file.isEmpty()) {
                return DerivativeResponse.success("文件为空", null);
            }

            String userName = "";
            String token = request.getHeader("token");
            if (userService.isInvokeGatewaySSO(token, "token")) {
                userName = userService.getIdFromToken(token);
            } else {
                userName = JwtHelper.parseToken(token).trim();
            }
            String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            String path = nasPath + time + "/" + uuid;
            //定义文件
            File parent = new File(path);
            if (!parent.exists()) parent.mkdirs();

            List<String> typeList = new ArrayList<>();
            typeList.add(".exe");
            typeList.add(".dll");
            String id = UUID.randomUUID().toString().replaceAll("-", "");
            String filename = file.getOriginalFilename();
            byte[] fileByte = file.getBytes();
            int potIndex = filename.lastIndexOf(".");
            String type = potIndex < 0 ? "" : filename.substring(potIndex);

            if (typeList.contains(type)) {
                return DerivativeResponse.error("失败", filename + " type forbiden");
            }
            if (StringUtils.hasText(dimension1) && DEPARTMENT_CAT_LIST.contains(catid)) {
                // 判断文件名是否包含当前上传维度的关键词，不包含则报错
                List<String> nameList = FILENAME_DEPARTMENT_MAP.get(dimension1);
                boolean flag = false;
                for (String name : nameList) {
                    if (filename.contains(name)) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    return DerivativeResponse.error("失败", "文件名[" + filename + "]与当前上传维度不匹配，请重新上传！");
                }
            }

            file.transferTo(new File(parent, filename));
            FileUploadLog fileUploadLog = new FileUploadLog();
            fileUploadLog.setId(id);
            fileUploadLog.setUploadTime(LocalDateTime.now());
            fileUploadLog.setUserName(userName);
            fileUploadLog.setFileName(filename);
            fileUploadLog.setPath(path + "/" + filename);
            fileUploadLog.setFile(fileByte);
            fileUploadService.saveUploadLog(fileUploadLog);

            FileUploadRelateImport fileUploadRelateImport = new FileUploadRelateImport();
            fileUploadRelateImport.setBizdate(bizdate);
            fileUploadRelateImport.setCatId(catid);
            fileUploadRelateImport.setFileId(id);
            fileUploadRelateImport.setDimension1(dimension1);
            fileUploadRelateImport.setIsDel(0);

            JSONObject fileinfo = new JSONObject();
            fileinfo.put("fileid", id);
            fileinfo.put("username", userName);
            fileinfo.put("filename", filename);
            fileinfo.put("time", fileUploadLog.getUploadTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            fileinfo.put("id", excelUploadService.relateImportMaxId() + 1);

            excelUploadService.saveRelateImport(fileUploadRelateImport);
            //以json方式输出到页面
            return DerivativeResponse.success("成功", fileinfo);
        } catch (Exception e) {
            return DerivativeResponse.error("错误", e.getMessage());
        }
    }

    @ApiOperation(value = "接口文件删除")
    @PostMapping("/importFileDelete")
    public DerivativeResponse delete(@RequestBody JSONObject jsonObject) {
        Long id = jsonObject.getLong("id");
        int ret = excelUploadService.deleteRelateImport(id);
        return DerivativeResponse.success("成功", ret);
    }

    @ApiOperation(value = "接口文件批量删除")
    @PostMapping("/importFileDeleteList")
    public DerivativeResponse deleteList(@RequestBody JSONObject jsonObject) {
        List<Long> idList = jsonObject.getJSONArray("idList").toJavaList(Long.class);
        int ret = excelUploadService.deleteRelateImport(idList);
        return DerivativeResponse.success("成功", ret);
    }

    @ApiOperation(value = "接口文件列表")
    @GetMapping("/importFileList")
    public DerivativeResponse fileList(@RequestParam(required = false, value = "catid") String catid,
                                       @RequestParam(required = false, value = "bizdate") String bizdate,
                                       @RequestParam(required = false, value = "dimension1") String dimension1) {
        List<ImportFileDto> ret = excelUploadService.importFileList(catid, bizdate, dimension1);
        ret.sort(Comparator.comparing(ImportFileDto::getId));
        return DerivativeResponse.success("成功", ret);
    }

    @ApiOperation(value = "获取状态")
    @GetMapping("/listStatus")
    public DerivativeResponse listStatus(@RequestParam(required = false, value = "catid") String catid,
                                         @RequestParam(required = false, value = "bizdate") String bizdate,
                                         @RequestParam(required = false, value = "dimension1") String dimension1) throws ParseException {
        List<JSONObject> ret = excelUploadService.listStatus(catid, bizdate, dimension1);
        Map<String, RegRptDefine> defineMap = regulatoryReportService.findAllRptDefineExist().
                stream().collect(Collectors.toMap(item -> item.getImportConfigId().toString(), item -> item));
        Date bizDate = new SimpleDateFormat("yyyyMM").parse(bizdate);

        Iterator<JSONObject> iterator = ret.iterator();
        while (iterator.hasNext()) {
            for (Map.Entry<String, Object> entry : iterator.next().entrySet()) {
                if (entry.getValue() == null) {
                    entry.setValue("");
                    continue;
                }
                String value = entry.getValue().toString();
                // 对有监管报送定义的数据额外处理
                if (entry.getKey().equals("importid") && defineMap.containsKey(value)) {
                    RegRptDefine define = defineMap.get(value);
                    // 过滤无效定义数据
                    if (NumberUtils.INTEGER_ZERO.equals(define.getIsEnable())) {
                        iterator.remove();
                        break;
                    }
                    // 过滤未启用定义数据
                    if (define.getEnableDate() != null && bizDate.before(define.getEnableDate())) {
                        iterator.remove();
                        break;
                    }
                    // 过滤已过期定义数据
                    if (define.getExpiryDate() != null && !bizDate.before(define.getExpiryDate())) {
                        iterator.remove();
                        break;
                    }
                }
                if (entry.getKey().equals("begintime") || entry.getKey().equals("endtime")) {
                    entry.setValue(value.substring(0, 19));
                }
            }
        }
        return DerivativeResponse.success("成功", ret);
    }

    @ApiOperation(value = "执行导入")
    @PostMapping("/doImport")
    public DerivativeResponse doImport(@RequestBody ExcelUploadDto param, HttpServletRequest request) {
        StringJoiner sj = new StringJoiner("<br/>");
        sj.add("成功");
        HashMap<String, String> ret = excelUploadService.doImport(param, request);
        for (Map.Entry<String, String> entry : ret.entrySet()) {
            if (entry.getValue().contains("接口未匹配到文件，已跳过导入")) {
                sj.add(MessageFormat.format("“{0}”接口未匹配到文件，已跳过导入", entry.getKey()));
            }
        }
        return DerivativeResponse.success(sj.toString(), ret);
    }

    @ApiOperation(value = "执行恢复")
    @PostMapping("/doRecovery")
    public DerivativeResponse doRecovery(@RequestBody ExcelUploadDto param) throws Exception {
        List<List> ret = excelUploadService.doRecovery(param);
        return DerivativeResponse.success("成功", ret);
    }

    @ApiOperation(value = "查询日期")
    @GetMapping("/queryBizdate")
    public DerivativeResponse queryBizdate(@RequestParam(required = true, value = "catid") String catid) throws Exception {
        List<String> ret = excelUploadService.queryBizdateByCatid(catid);
        return DerivativeResponse.success("成功", ret);
    }
}
